package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.heart.domain.*;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.order.*;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.service.IOrderService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 采购订单推送service
 */
@Component
@Slf4j
public class OrderPushService {

    private SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy-MM-dd HH:mm:ss" );

    private SimpleDateFormat sdfDate = new SimpleDateFormat ( "yyyy-MM-dd" );

    @Resource
    private IOrderService orderService;
    @Resource
    private IKingOrgService iKingOrgService;

    /**
     * 封装保存，提交，审核方法
     * @param orderId
     */
    @Transactional( rollbackFor = Exception.class )
    public void push(String orderId){
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity>().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity::getIsDisabled, false ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        OrderEntity order = orderService.selectOrderEntityById(orderId);
        if(Objects.isNull(order)){
            throw new CustomException("采购订单不存在！");
        }
        if(order.getIsSend() == KingConstUtil.KING_DATA_IS_SEND_YES){
            throw new CustomException("该单据已推送金蝶,无需重复推送！");
        }
        try {
            K3CloudApi client = new K3CloudApi ( identifyInfo );
            save(order,client);
            submit(order.getOrderNumber(),client);
            audit(order.getOrderNumber(),client);
            updateSendSuccess(order.getId(),order.getMoneyAmount());
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("推送采购订单失败！");
        }

    }

    /**
     * 修改推送状态
     * @param orderId
     * @return
     */
    private void updateSendSuccess(String orderId,String moneyAmount){
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setId(orderId);
        orderEntity.setIsSend(KingConstUtil.KING_DATA_IS_SEND_YES);
        orderEntity.setUpdateTime(DateUtils.getNowDate());
        orderEntity.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserId());
        orderEntity.setTotalUnpaidAmount(moneyAmount);
        boolean flag = orderService.updateById(orderEntity);
        if(!flag){
            throw new CustomException("修改推送状态失败！");
        }
    }


    /**
     * 金蝶保存方法
     * OrderEntity order,K3CloudApi client
     */
    public void save(OrderEntity order,K3CloudApi client){
        try{
            String formId = KingConstUtil.PUR_PurchaseOrder;
            KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
            OrderBo orderBo = this.assembleOrder(order);
            singleRequest.setModel(orderBo);
            //调用接口
            String resultJson = client.save(formId, JSONObject.toJSONString(singleRequest));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
               log.info("采购订单推送成功: {}", gson.toJson(repoRet.getResult()));
                List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
                if(!CollectionUtils.isEmpty(successEntities)){
                    String orderNumber = successEntities.get(0).getNumber();
                    //修改为已推送状态
                    IOrderService orderService = SpringUtils.getBean(IOrderService.class);
                    orderService.update(new LambdaUpdateWrapper<OrderEntity>().set(OrderEntity::getIsSend,KingConstUtil.KING_DATA_IS_SEND_YES).eq(OrderEntity::getOrderNumber,orderNumber));
                }
            } else {
                log.error("采购订单推送失败: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 金蝶提交方法
     * @param orderNumber
     * @param client
     */
    public void submit(String orderNumber,K3CloudApi client){
        try{
            OrderSubmitBo submitBo = new OrderSubmitBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(orderNumber);
            submitBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_PurchaseOrder;
            String resultJson = client.submit(formId, JSON.toJSONString ( submitBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("采购订单提交成功: {}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("采购订单提交失败:{} ",gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 金蝶审核方法
     * @param orderNumber
     * @param client
     */
    public void audit(String orderNumber,K3CloudApi client){
        try{
            OrderAuditBo auditBo = new OrderAuditBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(orderNumber);
            auditBo.setNumbers(numbers);
            String formId = KingConstUtil.PUR_PurchaseOrder;
            String resultJson = client.audit(formId,JSON.toJSONString ( auditBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("采购订单审核成功: {}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("采购订单审核失败: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 组装采购订单model对象
     * @param order
     * @return
     */
    private OrderBo assembleOrder(OrderEntity order){
        OrderBo orderBo = new OrderBo();
        //单据类型
        FBillTypeIDBo FBillTypeID = new FBillTypeIDBo().setFNUMBER(order.getDocType());
        orderBo.setFBillTypeID(FBillTypeID);
        //业务类型
        orderBo.setFBusinessType(order.getDocBusinessType());
        //单据编号
        orderBo.setFBillNo(order.getOrderNumber());
        //时间
        orderBo.setFDate(sdf.format(order.getCreateTime()));
        //供应商信息
        //order.getSupplierCode()
        FSupplierIdBo FSupplierId = new FSupplierIdBo().setFNumber("001");
        orderBo.setFSupplierId(FSupplierId);
        //采购组织-部门-采购组-采购员
        /**order.getPurchaseOrgCode()**/
        FPurchaseOrgIdBo FPurchaseOrgId = new FPurchaseOrgIdBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        orderBo.setFPurchaseOrgId(FPurchaseOrgId);
        FPurchaseDeptIdBo FPurchaseDeptId = new FPurchaseDeptIdBo().setFNumber(order.getPurchaseDeptCode());
        orderBo.setFPurchaseDeptId(FPurchaseDeptId);
        FPurchaserGroupIdBo FPurchaserGroupId  = new FPurchaserGroupIdBo().setFNumber(order.getPurchaseGroupCode());
        orderBo.setFPurchaserGroupId(FPurchaserGroupId);
        FPurchaserIdBo FPurchaserId = new FPurchaserIdBo().setFNumber(order.getApplyId());
        orderBo.setFPurchaserId(FPurchaserId);
        Optional.ofNullable(order.getOrderSupplier()).ifPresent(orderSupplier -> {
            //采购订单-供货方
            FProviderIdBo FProviderId = new FProviderIdBo().setFNumber(orderSupplier.getProviderCode());
            FProviderContactIdBo FProviderContactId = new FProviderContactIdBo().setFCONTACTNUMBER(orderSupplier.getProviderContacts());
            FSettleIdBo FSettleId = new FSettleIdBo().setFNumber(orderSupplier.getBalanceCode());
            FChargeIdBo FChargeId = new FChargeIdBo().setFNumber(orderSupplier.getReceiveCode());
            orderBo.setFProviderContactId(FProviderContactId);
            orderBo.setFProviderAddress(order.getOrderSupplier().getProviderAddress());
            orderBo.setFProviderId(FProviderId);
            orderBo.setFSettleId(FSettleId);
            orderBo.setFChargeId(FChargeId);
            orderBo.setFProviderEMail(orderSupplier.getEmail());
        });
        FConfirmerIdBo FConfirmerId = new FConfirmerIdBo().setFUserID(order.getConfirmName());
        orderBo.setFConfirmerId(FConfirmerId);
        if(Objects.nonNull(order.getConfirmTime())){
            orderBo.setFConfirmDate(sdf.format(order.getConfirmTime()));
        }
        //财务信息
        FPOOrderFinanceBo FPOOrderFinance = new FPOOrderFinanceBo();
        //结算方式
        FSettleModeIdBo FSettleModeId = new FSettleModeIdBo().setFNumber(order.getSettlementMethod());
        FPOOrderFinance.setFSettleModeId(FSettleModeId);
        //付款条件
        FPayConditionIdBo FPayConditionId = new FPayConditionIdBo().setFNumber(order.getTermOfPayment());
        FPOOrderFinance.setFPayConditionId(FPayConditionId);
        //结算币别
        FSettleCurrIdBo FSettleCurrId = new FSettleCurrIdBo().setFNumber(order.getSettlementCurrency());
        FPOOrderFinance.setFSettleCurrId(FSettleCurrId);
        //汇率类型
        FExchangeTypeIdBo FExchangeTypeId = new FExchangeTypeIdBo().setFNumber(order.getExchangeRateType());
        FPOOrderFinance.setFExchangeTypeId(FExchangeTypeId);
        FPOOrderFinance.setFExchangeRate(order.getExchangeRate());
        //价目表
        FPriceListIdBo FPriceListId = new FPriceListIdBo().setFNumber(order.getPriceInfoId());
        FPOOrderFinance.setFPriceListId(FPriceListId);
        //折扣表
        FDiscountListIdBo FDiscountListId = new FDiscountListIdBo().setFNumber(order.getDiscountInfoId());
        FPOOrderFinance.setFDiscountListId(FDiscountListId);
        FPOOrderFinance.setFPriceTimePoint(order.getPricingTimePoint());
        //集中结算组织
        //order.getFocusSettlementDept()
        FFOCUSSETTLEORGIDBo FFOCUSSETTLEORGID = new FFOCUSSETTLEORGIDBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        FPOOrderFinance.setFFOCUSSETTLEORGID(FFOCUSSETTLEORGID);
        FPOOrderFinance.setFIsIncludedTax(order.getIsTax());
        FPOOrderFinance.setFISPRICEEXCLUDETAX(order.getIsExtraPriceTax());
        FLocalCurrIdBo FLocalCurrId = new FLocalCurrIdBo().setFNumber(order.getBaseCurrency());
        FPOOrderFinance.setFLocalCurrId(FLocalCurrId);
//        FPOOrderFinance.setFDepositRatio(Integer.parseInt(order.getEnsureRate()));
        FPOOrderFinance.setFAllDisCount(0);
        FPOOrderFinance.setFUPPERBELIEL(0);
        orderBo.setFPOOrderFinance(FPOOrderFinance);
        orderBo.setFPOOrderPay(new FPOOrderPayBo());
        if(!CollectionUtils.isEmpty(order.getOrderPurchaseTerms())){
            //订单条款
            List<FPOOrderClauseBo> FPOOrderClause = order.getOrderPurchaseTerms().stream().filter(Objects::nonNull).map(term -> {
                KingPurchaseTermsEntity purchaseTerm = term.getPurchaseTerms();
                FPOOrderClauseBo orderClauseBo = new FPOOrderClauseBo();
                FClauseIdBo FClauseId = new FClauseIdBo().setFNumber(purchaseTerm.getCode());
                orderClauseBo.setFClauseId(FClauseId);
                orderClauseBo.setFClauseDesc(purchaseTerm.getDescribeInfo ( ));
                return orderClauseBo;
            }).collect(Collectors.toList());
            orderBo.setFPOOrderClause(FPOOrderClause);
        }
        if(!CollectionUtils.isEmpty(order.getOrderDetails())){
            //明细信息
            List<FPOOrderEntryBo> FPOOrderEntry = new ArrayList<>();
            order.getOrderDetails().forEach(detail -> {
                FPOOrderEntryBo orderEntry = new FPOOrderEntryBo();
                BaseChildBo FMaterialId = new BaseChildBo().setFNumber(detail.getMaterialCode());
                orderEntry.setFMaterialId(FMaterialId);
//                orderEntry.setFMaterialDesc(material.getMaterialDesc());
                BaseChildBo FUnitId = new BaseChildBo().setFNumber(detail.getPurchaseUnit());
                BaseChildBo FPriceUnitId = new BaseChildBo().setFNumber(detail.getPricingUnit());
                BaseChildBo FRequireOrgId = new BaseChildBo().setFNumber(detail.getRequireDept());
                BaseChildBo FReceiveOrgId = new BaseChildBo().setFNumber(detail.getReceivingDept());
                BaseChildBo FEntrySettleOrgId = new BaseChildBo().setFNumber(detail.getSettlementDept());
                BaseChildBo FStockUnitID = new BaseChildBo().setFNumber(detail.getInventoryUnit());
                BaseChildBo FLot = new BaseChildBo().setFNumber(detail.getBatchNum());
                orderEntry.setFUnitId(FUnitId);
                orderEntry.setFQty(detail.getNumber());
                orderEntry.setFPriceUnitId(FPriceUnitId);
                orderEntry.setFPriceUnitQty(detail.getPricingNum());
                orderEntry.setFPriceBaseQty(detail.getPricingNum());
                orderEntry.setFDeliveryDate(sdf.format(detail.getDeliveryDate()));
                orderEntry.setFLocation(detail.getDeliveryLocation());
                orderEntry.setFLocationAddress(detail.getDeliveryAddress());
                orderEntry.setFPrice(detail.getPrice());
                orderEntry.setFTaxPrice(detail.getTaxPrice ());
//                orderEntry.setFTaxPrice(Integer.parseInt(detail.getContainsTaxPrice()));
                orderEntry.setFEntryDiscountRate(detail.getDiscountRate());
                orderEntry.setFEntryTaxRate(detail.getTaxRate());
                //FRequireOrgId
                orderEntry.setFRequireOrgId(new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG));
                orderEntry.setFRequireOrgId(FReceiveOrgId);
                //
                orderEntry.setFEntrySettleOrgId(new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG));
                orderEntry.setFGiveAway(detail.getIsGiveaway());
                orderEntry.setFStockUnitID(FStockUnitID);
                orderEntry.setFStockQty(detail.getInventoryNum());
                orderEntry.setFStockBaseQty(detail.getInventoryNum());
                orderEntry.setFLot(FLot);
                //物料交货安排信息
                OrderDeliveryEntity orderDelivery = detail.getOrderDelivery();
                if(Objects.nonNull(orderDelivery)){
                    orderEntry.setFDeliveryControl(orderDelivery.getControlDeliveryNum());
                    orderEntry.setFTimeControl(orderDelivery.getControlDeliveryTime());
                    orderEntry.setFDeliveryMaxQty(Integer.parseInt(orderDelivery.getDeliveryUp()));
                    orderEntry.setFDeliveryMinQty(Integer.parseInt(orderDelivery.getDeliveryDown()));
                    orderEntry.setFDeliveryBeforeDays(Integer.parseInt(orderDelivery.getDeliveryLeadDay()));
                    orderEntry.setFDeliveryDelayDays(Integer.parseInt(orderDelivery.getDeliveryDelayDay()));
                    orderEntry.setFDeliveryEarlyDate(sdf.format(orderDelivery.getDeliveryEarlyTime()));
                    orderEntry.setFDeliveryLastDate(sdf.format(orderDelivery.getDeliveryLatestTime()));
                }
                //物料明细财务信息
                OrderFinanceDetailEntity orderFinanceDetail = detail.getOrderFinanceDetail();
                if(Objects.nonNull(orderFinanceDetail)){
                    orderEntry.setFPriceCoefficient(Integer.parseInt(orderFinanceDetail.getPriceCoefficient()));
                }
                BaseChildBo FSalUnitID = new BaseChildBo().setFNumber(detail.getPricingUnit());
                orderEntry.setFSalUnitID(FSalUnitID);
                orderEntry.setFSalQty(Integer.parseInt(detail.getPricingNum()));
                orderEntry.setFInventoryQty(detail.getInventoryNum());
                orderEntry.setFSalBaseQty(Integer.parseInt(detail.getPricingNum()));
                orderEntry.setFAllAmountExceptDisCount(Integer.parseInt(detail.getTotalTaxPrice()));
                List<FEntryDeliveryPlanBo> FEntryDeliveryPlan = new ArrayList<>();
                if(Objects.nonNull(detail.getOrderDelivery())){
                    if(!CollectionUtils.isEmpty(detail.getOrderDelivery().getOrderDeliveryDetails())){
                        List<OrderDeliveryDetailEntity> deliveryDetails = detail.getOrderDelivery().getOrderDeliveryDetails();
                        deliveryDetails.forEach(deliveryDetail -> {
                            FEntryDeliveryPlanBo deliveryPlanBo = new FEntryDeliveryPlanBo().setFDeliveryDate_Plan(sdfDate.format(deliveryDetail.getDeliveryTime()))
                            .setFPlanQty(Integer.parseInt(deliveryDetail.getNum())).setFELocation(deliveryDetail.getLocation()).setFELocationAddress(deliveryDetail.getAddress())
                            .setFSUPPLIERDELIVERYDATE(sdfDate.format(deliveryDetail.getDeliveryTime())).setFPREARRIVALDATE(sdfDate.format(deliveryDetail.getDeliveryTime()))
                            .setFConfirmDeliQty(Integer.parseInt(deliveryDetail.getConfirmNum())).setFConfirmDeliDate(sdfDate.format(deliveryDetail.getConfirmTime()))
                            .setFConfirmInfo(deliveryDetail.getConfirmComment());
                            FEntryDeliveryPlan.add(deliveryPlanBo);
                        });
                    }
                }
                orderEntry.setFEntryDeliveryPlan(FEntryDeliveryPlan);
                FPOOrderEntry.add(orderEntry);
            });
            orderBo.setFPOOrderEntry(FPOOrderEntry);
        }

        if(!CollectionUtils.isEmpty(order.getOrderPaymentPlans())){
            //付款计划
            List<FIinstallmentBo> FIinstallment = new ArrayList<>();
            List<OrderPaymentPlanEntity> orderPaymentPlans = order.getOrderPaymentPlans();
            orderPaymentPlans.stream().filter(Objects::nonNull).forEach(paymentPlan -> {
                FIinstallmentBo linstallmentBo = new FIinstallmentBo().setFYFDATE(sdfDate.format(paymentPlan.getPayableTime())).setFYFRATIO(Integer.parseInt(paymentPlan.getPayableRate()))
                        .setFYFAMOUNT(Integer.parseInt(paymentPlan.getPayableMoney())).setFISPREPAYMENT(paymentPlan.getIsPrepaid()).setFInsPrepaidAmount(Integer.parseInt(paymentPlan.getSinglePrepaidLimit()))
                        .setFRemarks(paymentPlan.getRemark());
                FIinstallment.add(linstallmentBo);
            });
            orderBo.setFIinstallment(FIinstallment);
        }

        return orderBo;
    }




}
